/*
 * ccveprocessor.h
 *
 * Copyright 2012 The University of Auckland
 *
 *  Created on: 20/06/2012
 *      Author: ccve
 */

#ifndef VRN_CCVEPROCESSOR_H
#define VRN_CCVEPROCESSOR_H

#include "voreen/core/processors/renderprocessor.h"
#include "voreen/core/properties/optionproperty.h"
#include "modules/flowreen/processors/flowreenprocessor.h"
#include "modules/flowreen/datastructures/simpletexture.h"

#include "voreen/core/ports/renderport.h"
#include "voreen/core/properties/filedialogproperty.h"
#include "voreen/core/properties/vectorproperty.h"
#include "voreen/core/properties/buttonproperty.h"
#include "tgt/shadermanager.h"

namespace voreen {

class CcveProcessor : public RenderProcessor, public FlowreenProcessor {
public:
	CcveProcessor();

    // virtual constructor
    virtual Processor* create() const;

    // documentary functions
    virtual std::string getClassName() const { return "CcveProcessor";       }
    virtual std::string getCategory() const  { return "Image Processing";      }
    virtual CodeState getCodeState() const   { return CODE_STATE_EXPERIMENTAL; }


protected:

    enum SliceAlignment {
    	// :-)
        PLANE_XY = 2,   /** view from the volume's front to back (negative z-axis) */
        PLANE_XZ = 1,   /** view from the volume's bottom to top (negative y-axis) */
        PLANE_ZY = 0    /** view from the volume's right to left (negative x-axis) */
    };

    enum InputTextureType {
    	WHITE_NOISE = 0,
    	SPARSE_NOISE = 1
    };

    enum TextureZoom {
        ZOOM_FULL_SIZE = 0,
        ZOOM_1X = 1,
        ZOOM_2X = 2,
        ZOOM_4X = 4,
        ZOOM_8X = 8
    };

    // used to distinguish between return values
    enum LICWarning {
    	ZERO_VECTOR = -1
    };

    enum ComboType {
    	// See Burkhards email 20 august 2012
    	WEIGHTED_ADDITION = 0,
    	OVERLAY = 1, // make both textures partially transparent (eg pixels w <.5 intensity transparent)
    	MASKING_CHECKERBOARD = 2,
    	MASKING_WEAVING = 3, // TODO maybe diamonds weaving
    	MASKING_WEAVING2 = 100,
    	MASKING_DIAGONAL = 4,
    	MASKING_VERTICAL = 5,
    	MASKING_HORIZONTAL = 6,
    	TOPOLOGICAL_BLENDING = 7, // compute topology for both vector fields & separate space into regions of consistent behaviour
    	MODIFY_LIC = 8, // modify the LIC method of the 2nd field by using results from the first LIC (eg use first texture as input for 2nd LIC)
    	BUMPMAPPING = 9,
    	DOUBLEBUMPMAPPING = 10
    };

    TextureZoom zoom_;

    virtual void setDescriptions() {
        setDescription("My thesis processor... TODO");
    }

    // actual rendering code
    virtual void process();

    /// loads the shader
    virtual void initialize() throw (VoreenException);

    /// frees the shader
    virtual void deinitialize() throw (VoreenException);

private:
    // ports and properties
    //RenderPort inport_;

    // ports
    VolumeCollectionPort inport_;
	VolumePort volPort1_;
	VolumePort volPort2_;
    RenderPort outport_;

    // properties
    FileDialogProperty grammarfile_;

    /* LIC PROPERTIES */
    IntProperty kernelSizeProp_;
    IntProperty kernelSizeProp2_;
    IntProperty pixelSamplingProp_;
    IntProperty pixelSamplingProp2_;
    BoolProperty useAdaptiveKernelSizeProp_;
    BoolProperty useAdaptiveKernelSizeProp2_;
    OptionProperty<InputTextureType>* textureTypeProp1_;
    OptionProperty<InputTextureType>* textureTypeProp2_;
    IntProperty sparseP1_;
    IntProperty sparseP2_;
    OptionProperty<SliceAlignment>* alignmentProp_;
    FloatVec2Property thresholdProp_;
    IntProperty sliceIndexProp_;

    /* BLENDING PROPERTIES */
    OptionProperty<ComboType>* comboProp_;

    /* PATTERN MASKING PROPERTIES */
    IntProperty patternWidthProp_; //TODO appear only if weaving is selected?
    IntProperty patternXDisplacementProp_; //TODO appear only if weaving is selected?
    IntProperty patternYDisplacementProp_; //TODO appear only if weaving is selected?
    IntProperty patternWeavingShadowProp_;
    BoolProperty patternWeavingSolidShadowProp_;

    /* OVERLAY PROPERTIES */
    IntProperty overlayTopFieldProp_;
    IntProperty overlayThresholdProp_;

    //colour channels for each LIC
    BoolProperty r_f1;
    BoolProperty g_f1;
    BoolProperty b_f1;
    BoolProperty r_f2;
    BoolProperty g_f2;
    BoolProperty b_f2;

    // vars
    /** the current 2D texture containing the flow image */
    tgt::Texture* sliceTexture_;

    /** the currently used slice alignment */
    SliceAlignment alignment_;

    /** permutation of the components of the flow according to selected slice alignment */
    tgt::ivec3 permutation_;

    // functions
    float CcveProcessor::getTextureScalingFactor( const tgt::vec2& viewportSize,
                                                  const tgt::vec2& textureSize   );

    float CcveProcessor::calculateVectorMagnitude( tgt::vec3 v );

    void onThresholdChange();
    void onSliceAlignmentChange();
    tgt::ivec3 getCoordinatePermutation(const SliceAlignment& alignment);


    bool loadShader(const std::string& vertexShaderName, const std::string& fragmentShaderName);
    std::string CcveProcessor::generateShaderHeader();


	tgt::vec4 getColour(float value);
    float clamp(float value, float min, float max);
    int clamp2(int value, int min, int max);
    tgt::vec3 mix(tgt::vec3 vec1, tgt::vec3 vec2, float fraction);

    tgt::Shader* shader_;

    float* pixels1;
    float* pixels2;
    float* colours;
    bool LICchanged;
    bool LICchanged2;
    void toggleLIC();
    void toggleLIC2();

    // methods to calculate several blending techniques
    void calculateWeightedAddition(int numElements, float* lic1, float* lic2);
    void calculateOverlay(int numElements, float* lic1, float* lic2);
    void calculateCheckerboardPattern(float* lic1, float* lic2, int xdim, int ydim);
    void calculateWeavingPattern(float* lic1, float* lic2, int xdim, int ydim);
    void calculateWeavingPattern2(float* lic1, float* lic2, int xdim, int ydim);
    void calculateDiagonalPattern(float* lic1, float* lic2, int xdim, int ydim);
    void calculateVerticalPattern(float* lic1, float* lic2, int xdim, int ydim);
    void calculateHorizontalPattern(float* lic1, float* lic2, int xdim, int ydim);
    void calculateTopologicalBlending(int numElements, float* lic1, float* lic2);
    void calculateBumpMapping(float* lic1, float* lic2, int xdim, int ydim);
    void calculateDoubleBumpMapping(float* lic1, float* lic2, int xdim, int ydim);
    void calculateModifyLIC(int numElements, float* lic);

    tgt::vec3 RGBtoHSV(tgt::vec3 rgb);
    tgt::vec3 HSVtoRGB(tgt::vec3 hsv);

    // helper, filters image with gaussian
    float calcGaussian(float* texture, int xdim, int ydim, int kernelsize, int x, int y);

    int previousComboType_;

    // GLSL shader
    //tgt::Shader* shader_;
};

} // namespace

#endif // VRN_CCVEPROCESSOR_H
